package cn.tedu.fy.pethome.service.impl;

import cn.tedu.fy.pethome.ex.ServiceException;
import cn.tedu.fy.pethome.mapper.AdminMapper;
import cn.tedu.fy.pethome.pojo.dto.AdminAddNewDTO;
import cn.tedu.fy.pethome.pojo.dto.AdminLoginDTO;
import cn.tedu.fy.pethome.pojo.entity.Admin;
import cn.tedu.fy.pethome.pojo.vo.AdminLoginVO;
import cn.tedu.fy.pethome.security.AdminDetails;
import cn.tedu.fy.pethome.service.IAdminService;
import cn.tedu.fy.pethome.util.JwtUtil;
import cn.tedu.fy.pethome.web.DataEnable;
import cn.tedu.fy.pethome.web.ServiceCode;
import cn.tedu.fy.pethome.web.UserLogin;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class AdminServiceImpl implements IAdminService {
    //持久层
    @Autowired
    private AdminMapper adminMapper;
    //编码器
    @Autowired
    private BCryptPasswordEncoder encoder;
    //认证官
    @Autowired
    private AuthenticationManager manager;


    //添加管理员,最高权限管理员才能有的业务
    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("adminService接收到的需要添加的数据为{}",adminAddNewDTO);

        //根据姓名去查有无重名管理员
        AdminLoginVO adminResult = adminMapper.getByUserName(adminAddNewDTO.getUsername());
        if(adminResult!=null){
            String message = "存在相同管理员名,请重新输入";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }

        //开始准备向数据库中存入admin的实体对象
        Admin admin = new Admin();
        //将DTO中数据复制给实体
        BeanUtils.copyProperties(adminAddNewDTO,admin);
        //补全其余admin的数据
        //将用户密码变为密文
        String NewPassword = encoder.encode(admin.getPassword());
        admin.setPassword(NewPassword);
        //默认登录ip
        admin.setLastLoginIp(UserLogin.DEFAULT_IP);
        //默认管理员登录次数
        admin.setLoginCount(0);
        //默认管理员登录时间
        admin.setGmtLastLogin(LocalDateTime.now());
        int rows = adminMapper.insert(admin);
        if(rows!=1){
            String message = "添加管理员失败,服务器忙,请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }


    }

    //管理员登录业务
    @Override
    public String login(AdminLoginDTO admin){
        log.debug("admin_login业务接收到的当事人信息为{}",admin);

        //创造未认证的认证信息
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                admin.getUsername(),admin.getPassword());

        //获得认证后的全部信息
        Authentication authenticate = manager.authenticate(authentication);

        //获得当事人详细信息
        AdminDetails principal = (AdminDetails) authenticate.getPrincipal();

        //准备管理员的jwt的相关参数
        Long id = principal.getId();
        log.debug("认证后的当事人id为{}",id);
        String username = principal.getUsername();
        log.debug("认证后的当事人的username为{}",username);
        Collection<GrantedAuthority> authorities = principal.getAuthorities();
        log.debug("当事人的权限为{}",authorities);
        //将权限转换为JSON格式String
        // bug fix: authenticate -> authorities
        String authorityString = JSON.toJSONString(authorities);

        //开始制作jwt
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",id);
        log.error("!!!!!{}",id.getClass().getName());
        claims.put("username",username);
        claims.put("authorities",authorityString);
        System.out.println("程序走到这里了");

        //生成jwt
        String jwt = JwtUtil.buildJwt(claims);
        log.debug("即将返回给controller的jwt为{}",jwt);
        return jwt;




    }



}
